home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / linuxcon.000 / linuxcon / linuxconf-1.6 / dnsconf / resolv.c < prev    next >
C/C++ Source or Header  |  1996-07-29  |  8KB  |  348 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <netdb.h>
  4. #include "dnsconf.h"
  5. #include "internal.h"
  6. #include "../dialog/dialog.h"
  7. #include "../xconf/xconf.h"
  8. #include "../userconf/userconf.h"
  9. #include "../paths.h"
  10. #include "dnsconf.m"
  11.  
  12. static DNSCONF_HELP_FILE help_resolv ("resolv");
  13. static DNSCONF_HELP_FILE help_host_conf ("host.conf");
  14. static CONFIG_FILE f_resolv (ETC_RESOLV_CONF,help_resolv
  15.     ,CONFIGF_MANAGED|CONFIGF_OPTIONNAL);
  16. static CONFIG_FILE f_host_conf (ETC_HOST_CONF,help_host_conf
  17.     ,CONFIGF_MANAGED|CONFIGF_OPTIONNAL);
  18.  
  19. PRIVATE void RESOLV::parse (const char *pt)
  20. {
  21.     int nb = 0;
  22.     while (*pt != '\0'){
  23.         pt = str_skip(pt);
  24.         char word[200];
  25.         pt = str_copyword(word,pt);
  26.         if (word[0] == '\0') break;
  27.         if (nb == MAX_SEARCH_RESOLV){
  28.             xconf_error (MSG_U(E_TOOMSEARCH
  29.                 ,"Too many entries in search statement\n"
  30.                  "in file %s")
  31.                 ,ETC_RESOLV_CONF);
  32.             break;
  33.         }
  34.         search[nb++].setfrom (word);
  35.     }
  36. }
  37.  
  38. PUBLIC RESOLV::RESOLV()
  39. {
  40.     FILE *fin = f_resolv.fopen("r");
  41.     if (fin != NULL){
  42.         char buf[300];
  43.         int noline = 0;
  44.         int nbservers = 0;
  45.         while (fgets(buf,sizeof(buf),fin)!= NULL){
  46.             char key[100];
  47.             char *pt = str_copyword(key,str_skip(buf));
  48.             noline++;
  49.  
  50.             /* #Specification: netconf / resolv.conf / comment
  51.                 netconf do not preserve, nor show, comments in
  52.                 /etc/resolv.conf. I am not even sure if they
  53.                 are allowed.
  54.             */
  55.             if (key[0] != '\0' && key[0] != '#'){
  56.                 pt = str_skip(pt);
  57.                 int err = 1;
  58.                 if (*pt != '\0'){
  59.                     err = 0;
  60.                     str_strip (pt,pt);
  61.                     if (strcmp(key,"domain")==0){
  62.                         domain.setfrom (pt);
  63.                     }else if (strcmp(key,"search")==0){
  64.                         parse (pt);
  65.                     }else if (strcmp(key,"nameserver")==0){
  66.                         servers[nbservers++].setfrom(pt);
  67.                     }else{
  68.                         err = 1;
  69.                     }
  70.  
  71.                 }
  72.                 if (err){
  73.                     xconf_error (MSG_U(E_IVLDLINE,"Invalid line %d in %s")
  74.                         ,noline,ETC_RESOLV_CONF);
  75.                 }
  76.             }
  77.         }
  78.         fclose (fin);
  79.     }
  80. }
  81.  
  82. PUBLIC int RESOLV::write ()
  83. {
  84.     int ret = -1;
  85.     FILE *fout = f_resolv.fopen ("w");
  86.     if (fout != NULL){
  87.         if (!domain.is_empty()) fprintf (fout,"domain %s\n"
  88.             ,domain.get());
  89.         const char *ctl = "search %s";
  90.         const char *endctl = "";
  91.         for (int i=0; i<MAX_SEARCH_RESOLV; i++){
  92.             if (!search[i].is_empty()){
  93.                 fprintf (fout,ctl,search[i].get());
  94.                 ctl = " %s";
  95.                 endctl = "\n";
  96.             }
  97.         }
  98.         fputs (endctl,fout);
  99.         for (i=0; i<3; i++){
  100.             if (servers[i].is_valid()){
  101.                 fprintf (fout,"nameserver %s\n"
  102.                     ,servers[i].get());
  103.             }
  104.         }
  105.         ret = fclose (fout);
  106.     }
  107.     return ret;
  108. }    
  109. static const char DNSCONF[]="DNSCONF";
  110. static const char DNSNEEDED[]="dnsneeded";
  111.  
  112. void dnsconf_editresolv()
  113. {
  114.     RESOLV res;
  115.     DIALOG dia;
  116.     char dnsneeded = (char)linuxconf_getvalnum (DNSCONF,DNSNEEDED,1);
  117.     dia.newf_chk (MSG_U(F_DNSNEEDED,"DNS usage"),dnsneeded
  118.         ,MSG_U(M_DNSNEEDED,"DNS is required for normal operation"));
  119.     dia.newf_str (MSG_U(F_DEFDOM,"default domain"),res.domain);
  120.     dia.newf_str (MSG_U(F_NAMESERV1,"nameserver 1"),res.servers[0]);
  121.     dia.newf_str (MSG_U(F_NAMESERV2,"nameserver 2 (opt)"),res.servers[1]);
  122.     dia.newf_str (MSG_U(F_NAMESERV3,"nameserver 3 (opt)"),res.servers[2]);
  123.     for (int i=0; i<MAX_SEARCH_RESOLV; i++){
  124.         char buf[100];
  125.         sprintf (buf,MSG_U(F_SEARCHDOM,"search domain %d (opt)"),i+1);
  126.         dia.newf_str (buf,res.search[i]);
  127.     }
  128.     int nofield = 0;
  129.     while (1){
  130.         if (dia.edit (
  131.             MSG_U(T_RESOLVCONF,"Resolver configuration")
  132.             ,MSG_U(I_RESOLVCONF
  133.              ,"You can specify which name server will be used\n"
  134.               "to resolv host ip number. Using the DNS is\n"
  135.               "to handle this on a TCP/IP network. The others\n"
  136.               "are the local /etc/hosts file\n"
  137.               "   (see \"information about other hosts\" menu\n"
  138.               "or the NIS system\n")
  139.             ,help_resolv.getpath()
  140.             ,nofield) != MENU_ACCEPT){
  141.             break;
  142.         }else{
  143.             /* We must validate the input somehow */
  144.             SSTRING error;
  145.             for (int n=0; n<3; n++){
  146.                 IP_ADDR *s = res.servers + n;
  147.                 if (!s->is_empty()
  148.                     && !s->is_valid()){
  149.                     char msg[100];
  150.                     sprintf (msg,MSG_U(E_IVLDIP
  151.                         ,"Invalid IP number for nameserver %d\n"),n+1);
  152.                     error.append (msg);
  153.                 }
  154.             }
  155.             if (error.is_empty()){
  156.                 if (res.write() != -1){
  157.                     linuxconf_replace (DNSCONF,DNSNEEDED,dnsneeded);
  158.                     linuxconf_save();
  159.                     break;
  160.                 }
  161.             }else{
  162.                 xconf_error (error.get());
  163.             }
  164.         }
  165.     }
  166. }
  167.  
  168. /*
  169.     Return != 0 if there is at least one nameserver specified in
  170.     /etc/resolv.conf (IsReSoLv Configured).
  171.  
  172.     The resolver will use 127.0.0.1 if there is no nameserver entry, but
  173.     some routine of linuxconf may assume that if there is no explicit
  174.     nameserver, then this machine does not have one running either.
  175.  
  176.     This function also check if the DNS is really needed for normal
  177.     operation of the computer. It will return 0 if the DNS is not needed.
  178. */
  179. int dnsconf_isrslconf()
  180. {
  181.     int ret = 0;
  182.     if (linuxconf_getvalnum (DNSCONF,DNSNEEDED,1)){
  183.         RESOLV res;
  184.         for (unsigned i=0; i<sizeof(res.servers)/sizeof(res.servers[0]); i++){
  185.             if (!res.servers[i].is_empty()){
  186.                 ret = 1;
  187.                 break;
  188.             }
  189.         }        
  190.     }
  191.     return ret;
  192. }
  193.  
  194. // Do not translate
  195. static const char *tborder[]={
  196.     "hosts, nis, bind",
  197.     "hosts, nis",
  198.     "hosts, bind, nis",
  199.     "hosts, bind",
  200.     "hosts",
  201.     "nis, hosts, bind",
  202.     "nis, hosts",
  203.     "nis, bind, hosts",
  204.     "nis, bind",
  205.     "nis",
  206.     "bind, hosts, nis",
  207.     "bind, hosts",
  208.     "bind, nis, hosts",
  209.     "bind, nis",
  210.     "bind",
  211.     NULL,
  212. };
  213.  
  214. /*
  215.     Do a string compare but compare only visible char (> ' ')
  216. */
  217. static int dnsconf_strcmp(const char *str1, const char *str2)
  218. {
  219.     int ret = -1;
  220.     while (1){
  221.         str1 = str_skip(str1);
  222.         str2 = str_skip(str2);
  223.         if (*str1 == *str2){
  224.             if (*str1 == '\0'){
  225.                 ret = 0;
  226.                 break;
  227.             }else{
  228.                 str1++;    
  229.                 str2++;
  230.             }
  231.         }else{
  232.             ret = *str1 - *str2;
  233.             break;
  234.         }
  235.     }
  236.     return ret;
  237. }
  238.  
  239.  
  240. /*
  241.     Read /etc/host.conf
  242. */
  243. static void dnsconf_readhostconf (
  244.     char &multi,    // Tell if the "multi" statement was seen
  245.     char &order)    // Will contain an index into tborder[]
  246. {
  247.     FILE *fin = f_host_conf.fopen ("r");
  248.     multi = 0;
  249.     order = 0;
  250.     if (fin != NULL){
  251.         char buf[300];
  252.         int noline = 0;
  253.         while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
  254.             noline++;
  255.             char key[300];
  256.             char *pt = str_copyword (key,buf);
  257.             if (strcmp(key,"multi")==0){
  258.                 multi = 1;
  259.             }else if (strcmp(key,"order")==0){
  260.                 for (int i=0; tborder[i] != NULL; i++){
  261.                     if (dnsconf_strcmp(tborder[i],pt)==0){
  262.                         order = i;
  263.                         break;
  264.                     }
  265.                 }
  266.             }else{
  267.                 xconf_error (MSG_U(E_IVLDKEYW
  268.                     ,"Invalid keyword %s\n"
  269.                      "in file %s, line %d")
  270.                     ,key,f_host_conf.getpath()
  271.                     ,noline);
  272.             }
  273.         }
  274.         fclose (fin);
  275.     }
  276. }
  277. /*
  278.     Write /etc/host.conf
  279. */
  280. static void dnsconf_writehostconf (
  281.     char multi,    // Tell if the "multi" statement was seen
  282.     char order)    // Will contain an index into tborder[]
  283. {
  284.     FILE *fout = f_host_conf.fopen ("w");
  285.     if (fout != NULL){
  286.         fprintf (fout,"order %s\n",tborder[order]);
  287.         if (multi) fputs ("multi on\n",fout);
  288.         fclose (fout);
  289.     }
  290. }
  291.  
  292. /*
  293.     Edit the file /etc/host.conf
  294. */
  295. void dnsconf_editorder()
  296. {
  297.     char multi;
  298.     char order;
  299.     dnsconf_readhostconf(multi,order);
  300.     DIALOG dia;
  301.  
  302.     dia.newf_chk ("",multi,MSG_U(F_MULTI,"Multiple IPs for one host"));
  303.     dia.newf_title ("","");
  304.     // User friendy version of tborder. It must have the same
  305.     // order, line by line. "bind" just mean nothing to most people.
  306.     static const char *tborder_v[]={
  307.         "hosts, NIS, dns",
  308.         "hosts, NIS",
  309.         "hosts, dns, NIS",
  310.         "hosts, dns",
  311.         "hosts",
  312.         "NIS, hosts, dns",
  313.         "NIS, hosts",
  314.         "NIS, dns, hosts",
  315.         "NIS, dns",
  316.         "NIS",
  317.         "dns, hosts, NIS",
  318.         "dns, hosts",
  319.         "dns, NIS, hosts",
  320.         "dns, NIS",
  321.         "dns",
  322.         NULL
  323.     };
  324.     for (int i=0; tborder_v[i] != NULL; i++){
  325.         dia.newf_radio ("",order,i,tborder_v[i]);
  326.     }
  327.     while (1){
  328.         if (dia.edit (MSG_U(T_NAMESERV,"Name service access")
  329.             ,MSG_U(I_NAMESERV
  330.              ,"You must tell the system in which order\n"
  331.               "the various name services must be probed\n"
  332.              "\n"
  333.              "hosts mean /etc/hosts is probed\n"
  334.              "NIS stand for Network Information System\n"
  335.              "dns stands for Domain Name Service\n")
  336.             ,help_host_conf.getpath()
  337.             ,0)!=MENU_ACCEPT){
  338.             break;
  339.         }else{
  340.             if (perm_rootaccess(MSG_U(P_WRITEHOSTS,"write /etc/host.conf"))){
  341.                 dnsconf_writehostconf (multi,order);
  342.                 break;
  343.             }
  344.         }
  345.     }
  346. }
  347.  
  348.